package com.shixforever.reader.activity;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
import java.util.Vector;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;

/**********************************************************
 * @文件名称：BookPageFactory.java
 * @文件作者：shixiang
 * @文件描述：book工厂 设置book相关属性
 * @修改历史：2012-1-5创建初始版本
 **********************************************************/
public class BookPageFactory
{

	private File book_file = null;
	private MappedByteBuffer m_mbBuf = null;
	private int m_mbBufLen = 0;
	private int m_mbBufBegin = 0;
	private int m_mbBufEnd = 0;
	private String m_strCharsetName = "GBK";
	private Bitmap m_book_bg = null;
	private int mWidth;
	private int mHeight;

	private Vector<String> m_lines = new Vector<String>();

	public int m_fontSize;// 字体大小
	SharedPreferences preferences;
	SharedPreferences.Editor edit;
	private int m_textColor = Color.BLACK;
	private int m_backColor = 0xffff9e85;
	private int marginWidth = 20;
	private int marginHeight = 40;

	private int mLineCount;
	private float mVisibleHeight;
	private float mVisibleWidth;
	private boolean m_isfirstPage, m_islastPage;

	// private int m_nLineSpaceing = 5;

	private Paint mPaint;

	public BookPageFactory(Context context, int w, int h)
	{
		mWidth = w;
		mHeight = h;
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mPaint.setTextAlign(Align.LEFT);
		// ----------------------------------------
		preferences = context.getSharedPreferences("config",
				Context.MODE_PRIVATE);
		edit = preferences.edit();
		int size = preferences.getInt("size", 30);
		m_fontSize = size;
		// -----------------------------------------------
		mPaint.setTextSize(m_fontSize);
		mPaint.setColor(m_textColor);
		mVisibleWidth = mWidth - marginWidth * 2;
		mVisibleHeight = mHeight - marginHeight * 2;
		mLineCount = (int) (mVisibleHeight / m_fontSize); 
	}

	public void openbook(String strFilePath, int begin) throws IOException
	{
		book_file = new File(strFilePath);
		long lLen = book_file.length();
		m_mbBufLen = (int) lLen;
		m_mbBuf = new RandomAccessFile(book_file, "r").getChannel().map(
				FileChannel.MapMode.READ_ONLY, 0, lLen);
		if (begin >= 0)
		{
			m_mbBufBegin = begin;
			m_mbBufEnd = begin;
		} else
		{
		}
	}

	// 新增加的方法，设置字体大小
	public void setTextSize(int a)
	{
		this.m_fontSize = a;
		mPaint.setTextSize(a);
		mLineCount = (int) (mVisibleHeight / m_fontSize);
		m_lines = pageDown(true);

		// edit.putInt("size", a);
		// edit.commit();

	}

	protected byte[] readParagraphBack(int nFromPos)
	{
		int nEnd = nFromPos;
		int i;
		byte b0, b1;
		if (m_strCharsetName.equals("UTF-16LE"))
		{
			i = nEnd - 2;
			while (i > 0)
			{
				b0 = m_mbBuf.get(i);
				b1 = m_mbBuf.get(i + 1);
				if (b0 == 0x0a && b1 == 0x00 && i != nEnd - 2)
				{
					i += 2;
					break;
				}
				i--;
			}

		} else if (m_strCharsetName.equals("UTF-16BE"))
		{
			i = nEnd - 2;
			while (i > 0)
			{
				b0 = m_mbBuf.get(i);
				b1 = m_mbBuf.get(i + 1);
				if (b0 == 0x00 && b1 == 0x0a && i != nEnd - 2)
				{
					i += 2;
					break;
				}
				i--;
			}
		} else
		{
			i = nEnd - 1;
			while (i > 0)
			{
				b0 = m_mbBuf.get(i);
				if (b0 == 0x0a && i != nEnd - 1)
				{
					i++;
					break;
				}
				i--;
			}
		}
		if (i < 0)
			i = 0;
		int nParaSize = nEnd - i;
		int j;
		byte[] buf = new byte[nParaSize];
		for (j = 0; j < nParaSize; j++)
		{
			buf[j] = m_mbBuf.get(i + j);
		}
		return buf;
	}

	protected byte[] readParagraphForward(int nFromPos)
	{
		int nStart = nFromPos;
		int i = nStart;
		byte b0, b1;
		if (m_strCharsetName.equals("UTF-16LE"))
		{
			while (i < m_mbBufLen - 1)
			{
				b0 = m_mbBuf.get(i++);
				b1 = m_mbBuf.get(i++);
				if (b0 == 0x0a && b1 == 0x00)
				{
					break;
				}
			}
		} else if (m_strCharsetName.equals("UTF-16BE"))
		{
			while (i < m_mbBufLen - 1)
			{
				b0 = m_mbBuf.get(i++);
				b1 = m_mbBuf.get(i++);
				if (b0 == 0x00 && b1 == 0x0a)
				{
					break;
				}
			}
		} else
		{
			while (i < m_mbBufLen)
			{
				b0 = m_mbBuf.get(i++);
				if (b0 == 0x0a)
				{
					break;
				}
			}
		}
		int nParaSize = i - nStart;
		byte[] buf = new byte[nParaSize];
		for (i = 0; i < nParaSize; i++)
		{
			buf[i] = m_mbBuf.get(nFromPos + i);
		}
		return buf;
	}

	protected Vector<String> pageDown(boolean size)
	{
		String strParagraph = "";
		Vector<String> lines = new Vector<String>();
		// 如果真的话字体变化改变数据
		if (size)
		{
			m_mbBufEnd = m_mbBufBegin;
		}
		while (lines.size() < mLineCount && m_mbBufEnd < m_mbBufLen)
		{
			byte[] paraBuf = readParagraphForward(m_mbBufEnd); // ��ȡһ������
			m_mbBufEnd += paraBuf.length;
			try
			{
				strParagraph = new String(paraBuf, m_strCharsetName);
			} catch (UnsupportedEncodingException e)
			{
				e.printStackTrace();
			}
			String strReturn = "";
			if (strParagraph.indexOf("\r\n") != -1)
			{
				strReturn = "\r\n";
				strParagraph = strParagraph.replaceAll("\r\n", "");
			} else if (strParagraph.indexOf("\n") != -1)
			{
				strReturn = "\n";
				strParagraph = strParagraph.replaceAll("\n", "");
			}

			if (strParagraph.length() == 0)
			{
				lines.add(strParagraph);
			}
			while (strParagraph.length() > 0)
			{
				int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,
						null);
				lines.add(strParagraph.substring(0, nSize));
				strParagraph = strParagraph.substring(nSize);
				if (lines.size() >= mLineCount)
				{
					break;
				}
			}
			if (strParagraph.length() != 0)
			{
				try
				{
					m_mbBufEnd -= (strParagraph + strReturn)
							.getBytes(m_strCharsetName).length;
				} catch (UnsupportedEncodingException e)
				{
					e.printStackTrace();
				}
			}
		}
		return lines;
	}

	protected void pageUp()
	{
		if (m_mbBufBegin < 0)
			m_mbBufBegin = 0;
		Vector<String> lines = new Vector<String>();
		String strParagraph = "";
		while (lines.size() < mLineCount && m_mbBufBegin > 0)
		{
			Vector<String> paraLines = new Vector<String>();
			byte[] paraBuf = readParagraphBack(m_mbBufBegin);
			m_mbBufBegin -= paraBuf.length;
			try
			{
				strParagraph = new String(paraBuf, m_strCharsetName);
			} catch (UnsupportedEncodingException e)
			{
				e.printStackTrace();
			}
			strParagraph = strParagraph.replaceAll("\r\n", "");
			strParagraph = strParagraph.replaceAll("\n", "");

			if (strParagraph.length() == 0)
			{
				paraLines.add(strParagraph);
			}
			while (strParagraph.length() > 0)
			{
				int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,
						null);
				paraLines.add(strParagraph.substring(0, nSize));
				strParagraph = strParagraph.substring(nSize);
			}
			lines.addAll(0, paraLines);
		}
		while (lines.size() > mLineCount)
		{
			try
			{
				m_mbBufBegin += lines.get(0).getBytes(m_strCharsetName).length;
				lines.remove(0);
			} catch (UnsupportedEncodingException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		m_mbBufEnd = m_mbBufBegin;
		return;
	}

	protected void prePage() throws IOException
	{
		if (m_mbBufBegin <= 0)
		{
			m_mbBufBegin = 0;
			m_isfirstPage = true;
			return;
		} else
			m_isfirstPage = false;
		m_lines.clear();
		pageUp();
		m_lines = pageDown(false);
	}

	public void nextPage() throws IOException
	{
		if (m_mbBufEnd >= m_mbBufLen)
		{
			m_islastPage = true;
			return;
		} else
			m_islastPage = false;
		m_lines.clear();
		m_mbBufBegin = m_mbBufEnd;
		m_lines = pageDown(false);
	}

	public void currentPage() throws IOException
	{
		m_lines.clear();
		m_lines = pageDown(false);
	}

	public void onDraw(Canvas c)
	{
		if (m_lines.size() == 0)
			m_lines = pageDown(false);
		if (m_lines.size() > 0)
		{
			if (m_book_bg == null)
				c.drawColor(m_backColor);
			else
				c.drawBitmap(m_book_bg, 0, 0, null);
			int y = marginHeight;
			for (String strLine : m_lines)
			{
				y += m_fontSize;
				c.drawText(strLine, marginWidth, y, mPaint);
			}
		}
		float fPercent = (float) (m_mbBufBegin * 1.0 / m_mbBufLen);
		DecimalFormat df = new DecimalFormat("#0.0");
		String strPercent = df.format(fPercent * 100) + "%";
		int nPercentWidth = (int) mPaint.measureText("999.9%") + 1;
		c.drawText(strPercent, mWidth - nPercentWidth, mHeight - 5, mPaint);
	}

	public void setBgBitmap(Bitmap BG)
	{
		m_book_bg = BG;
	}

	public boolean isfirstPage()
	{
		return m_isfirstPage;
	}

	public boolean islastPage()
	{
		return m_islastPage;
	}

	public int getM_mbBufBegin()
	{
		return m_mbBufBegin;
	}

	public void setM_mbBufBegin(int m_mbBufBegin)
	{
		this.m_mbBufBegin = m_mbBufBegin;
	}

	public int getM_fontSize()
	{
		return m_fontSize;
	}

	public String getFirstLineText()
	{
		return m_lines.size() > 0 ? m_lines.get(0) : "";
	}
	public String getSecLineText()
	{
		return m_lines.size() > 0 ? m_lines.get(1) : "";
	}
	public void setM_fontSize(int m_fontSize)
	{
		this.m_fontSize = m_fontSize;
		mLineCount = (int) (mVisibleHeight / m_fontSize) - 1;
	}

	public void setM_mbBufEnd(int m_mbBufEnd)
	{
		this.m_mbBufEnd = m_mbBufEnd;
	}

	public int getM_mbBufLen()
	{
		return m_mbBufLen;
	}
	public void turnMark()
	{
		m_lines.clear();
		m_lines = pageDown(true);
	}
}
